package com.cy.sca.api.aspect;

import com.cy.sca.api.feign.RemoteNoticeService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;

@Aspect //此注解描述的类为切面类
@Component //描述的类交给spring管理
public class LogAspect {

    private static final Logger log = LoggerFactory.getLogger(LogAspect.class);

    @Autowired
    private RemoteNoticeService remoteNoticeService;

    /**
     * 切入点的定义
     * @annotation为细粒度
     */
    @Pointcut("@annotation(com.cy.sca.api.annotation.RequiredLog)")
    public void doLog() {

    }

    /**
     * @around 环绕通知
     * @param jp 连接点（封装想要调用的目标方法）
     * @return 目标方法的返回结果
     */
    @Around("doLog()")
    public Object doAround(ProceedingJoinPoint jp) throws Throwable {

        //构建map用于存储log信息，后面需求时需定义pojo对象进行封装
        HashMap<String, Object> logInfoMap = new HashMap<>();

        String targetClassName = jp.getTarget().getClass().getName(); //获取目标类的类全名
        logInfoMap.put("targetClassName",targetClassName);
        //System.out.println("targetClassName:" + targetClassName);
        Signature signature = jp.getSignature(); //方法签名，包含方法信息
        String methodName = signature.getName();
        logInfoMap.put("methodName", methodName);
        //System.out.println("methodName:" + methodName);
        Object[] args = jp.getArgs(); //获取方法的参数，会暴露用户输入的密码信息
        String json = new ObjectMapper().writeValueAsString(args);
        logInfoMap.put("jsonArgs",json);
        //System.out.println("jsogArgs" + json);

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd 'at' hh:mm:ss:ms z");
        Date date1 = new Date(System.currentTimeMillis());
        logInfoMap.put("startTime", dateFormat.format(date1));
        System.out.println("start:" + dateFormat.format(date1));

        try {
            Object result = jp.proceed();//执行切面链（最终执行目标方法）

            Date date2 = new Date(System.currentTimeMillis());
            logInfoMap.put("status", 1);
            logInfoMap.put("afterTime", dateFormat.format(date2));
            System.out.println("after:" + dateFormat.format(date2));
            return result;
        } catch (Throwable e) {
            Date date3 = new Date(System.currentTimeMillis());
            logInfoMap.put("status", 2);
            logInfoMap.put("errorMsg:", e.getMessage());
            logInfoMap.put("afterTime", dateFormat.format(date3));
            System.out.println("error:" + dateFormat.format(date3));
            throw e;
        } finally {

            //记录日志信息
            log.info("operation log {} ",logInfoMap.toString());
            remoteNoticeService.doLoginfo(logInfoMap);

        }

    }

}
